package com.haoxuer.discover.approve.data.dao.impl;

import com.haoxuer.discover.approve.data.dao.*;
import com.haoxuer.discover.approve.data.entity.*;
import com.haoxuer.discover.approve.listener.OnStateChange;
import com.haoxuer.discover.config.data.entity.User;
import com.haoxuer.discover.data.core.CriteriaDaoImpl;
import com.haoxuer.discover.data.core.Finder;
import com.haoxuer.discover.data.core.Pagination;
import com.haoxuer.discover.data.page.Filter;
import com.haoxuer.discover.data.rest.domain.AbstractVo;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Repository
public class FlowDaoImpl extends CriteriaDaoImpl<Flow, Long> implements FlowDao {
  public Pagination getPage(int pageNo, int pageSize) {
    Criteria crit = createCriteria();
    Pagination page = findByCriteria(crit, pageNo, pageSize);
    return page;
  }


  public Flow findById(Long id) {
    Flow entity = get(id);
    return entity;
  }

  public Flow save(Flow bean) {
    getSession().save(bean);
    return bean;
  }

  public Flow deleteById(Long id) {
    Flow entity = super.get(id);
    if (entity != null) {
      getSession().delete(entity);
    }
    return entity;
  }

  @Override
  public Flow stop(Long id,String note) {
    Flow flow = findById(id);
    if (flow == null) {
      return null;
    }
    Task task = taskDao.findByFlow(id);
    if (task != null) {
      task.setState(1);
      task.setNote(note);

      FlowRecord record=new FlowRecord();
      record.setFlow(flow);
      record.setHierarchy(flow.getHierarchy());
      //record.setUser(task.getUser());
      record.setNote(note);
      record.setState(2);
      flowRecordDao.save(record);
    }

    return flow;
  }

  @Autowired
  private FlowDefinitionDao flowDefinitionDao;

  @Autowired
  FlowApprovalDao flowApprovalDao;

  @Resource
  private List<OnStateChange> changes = new ArrayList<>();

  @Autowired
  FlowRecordDao flowRecordDao;


  @Autowired
  TaskDao taskDao;

  @Override
  public Flow start(Flow flow) {
    FlowDefinition definition = flow.getFlow();
    if (definition == null) {
      return null;
    }
    flow.setCatalog(Integer.valueOf("" + definition.getId()));
    flow.setState(0);
    flow.setHierarchy(1);

    Finder finder = Finder.create();
    finder.append("from Flow f where f.catalog=:catalog");
    finder.append(" and f.oid=:oid");
    finder.setParam("catalog", flow.getCatalog());
    finder.setParam("oid", flow.getOid());
    List<Flow> flows = find(finder);
    if (flows != null && !flows.isEmpty()) {
      return flows.get(0);
    }
    flow = save(flow);
    FlowDefinition fs = flowDefinitionDao.findById(definition.getId());
    User taskuser = null;

    List<FlowDefinitionItem> vos = fs.getItems();
    if (vos != null) {
      for (FlowDefinitionItem approverVo : vos) {
        FlowApproval approval = new FlowApproval();
        approval.setFlow(flow);
        approval.setHierarchy(approverVo.getHierarchy());
        approval.setUser(approverVo.getUser());
        flowApprovalDao.save(approval);
        if (approverVo.getHierarchy() == 1) {
          taskuser = approverVo.getUser();
        }
      }
    }
    if (taskuser != null) {
      Task task = new Task();
      task.setUser(taskuser);
      task.setCatalog(flow.getCatalog());
      task.setOid(flow.getOid());
      task.setTitle(flow.getTitle());
      task.setNote(flow.getNote());
      task.setFlow(flow);
      task.setState(0);
      task.setStyle(1);
      taskDao.save(task);
    }
    return flow;
  }

  @Override
  public AbstractVo approve(Long taskid, Integer state, String note, Long user) {
    AbstractVo restult = new AbstractVo();
    Task curtask = taskDao.findById(taskid);
    User worker = User.fromId(user);
    if (worker == null) {
      restult.setCode(-4);
      restult.setMsg("非法用户");
    }
    if (worker != null) {
      if (!worker.getId().equals(curtask.getUser().getId())) {
        restult.setCode(-5);
        restult.setMsg("非法操作");
      }

    }
    if (curtask == null) {
      restult.setCode(-3);
      restult.setMsg("该任务不存在");
      return restult;
    }
    if (curtask.getState() == 1) {
      restult.setCode(-1);
      restult.setMsg("该任务已经处理过了");
      return restult;
    }
    Flow flow = curtask.getFlow();
    if (flow.getState() == 2) {
      restult.setCode(-2);
      restult.setMsg("该流程已经审核过了");
      return restult;
    }

    if (flow.getHierarchy() == 0) {
      state = 1;
    }

    curtask.setState(1);

    // 同意审核
    if (state == 1) {
      FlowRecord bean = new FlowRecord();
      bean.setState(1);
      bean.setHierarchy(curtask.getFlow().getHierarchy());
      bean.setUser(curtask.getUser());
      bean.setNote(note);
      bean.setFlow(flow);
      flowRecordDao.save(bean);
      FlowApproval ap = flowApprovalDao.findNext(curtask.getFlow().getId(), curtask.getFlow().getHierarchy());
      // 审批结束
      if (ap == null) {
        if (flow != null) {

          flow.setState(2);
          // 完成以后应该有个事件
          // if (flows != null) {
          // for (OnFlowFinshed onFlowFinshed : flows) {
          // onFlowFinshed.finded(flow);
          // }
          // }

          if (changes != null) {
            for (OnStateChange onStateChange : changes) {
              onStateChange.change(flow, "审核完成");
            }
          }

        }
      } else {
        // 该节点审核结束，进入他的下一个节点
        if (flow != null) {
          flow.setState(1);
          flow.setHierarchy(ap.getHierarchy());
        }
        Task task = new Task();
        task.setUser(ap.getUser());
        task.setCatalog(flow.getCatalog());
        task.setOid(flow.getOid());
        task.setTitle(flow.getTitle());
        task.setNote(flow.getNote());
        task.setFlow(flow);
        task.setState(0);
        task.setStyle(1);
        taskDao.save(task);

        if (changes != null) {
          for (OnStateChange onStateChange : changes) {
            onStateChange.change(flow, "审核中");
          }
        }
      }

    } else {
      Integer hInteger = flow.getHierarchy();
      // 拒绝审核
      flow.setHierarchy(0);
      flow.setState(-1);

      Task task = new Task();
      task.setUser(curtask.getFlow().getUser());
      task.setCatalog(flow.getCatalog());
      task.setOid(flow.getOid());
      task.setTitle(flow.getTitle());
      task.setNote(flow.getNote());
      task.setFlow(flow);
      task.setState(0);
      task.setStyle(-1);
      taskDao.save(task);

      FlowRecord bean = new FlowRecord();
      bean.setState(0);
      bean.setHierarchy(hInteger);
      bean.setUser(curtask.getUser());
      bean.setNote(note);
      bean.setFlow(flow);
      flowRecordDao.save(bean);

      if (changes != null) {
        for (OnStateChange onStateChange : changes) {
          onStateChange.change(flow, "审核失败");
        }
      }

    }

    return restult;
  }

  @Override
  public AbstractVo restart(Long taskid) {
    AbstractVo result = new AbstractVo();
    Task task = taskDao.findById(taskid);
    if (task != null) {
      task.setState(1);
      Flow flow = task.getFlow();
      if (flow != null) {
        flow.setHierarchy(1);
        flow.setState(0);
        for (OnStateChange onStateChange : changes) {
          onStateChange.change(flow, "审批中");
        }
      }
      FlowApproval approval = flowApprovalDao.findNext(flow.getId(), 0);
      if (approval != null) {
        Task newtask = new Task();
        newtask.setUser(approval.getUser());
        newtask.setCatalog(flow.getCatalog());
        newtask.setOid(flow.getOid());
        newtask.setTitle(flow.getTitle());
        newtask.setNote(flow.getNote());
        newtask.setFlow(flow);
        newtask.setState(0);
        newtask.setStyle(1);
        taskDao.save(newtask);

      }
    }
    return result;
  }

  @Override
  protected Class<Flow> getEntityClass() {
    return Flow.class;
  }

  @Autowired
  public void setSuperSessionFactory(SessionFactory sessionFactory) {
    super.setSessionFactory(sessionFactory);
  }

  @Override
  public Flow findByOId(Integer catalog, Long id) {
    Finder finder = Finder.create();
    finder.append("from Flow f where f.oid =:oid");
    finder.setParam("oid", id);
    finder.append("  and f.catalog =:catalog");
    finder.setParam("catalog", catalog);
    return findOne(finder);
  }

  @Override
  public int deleteForCatalog(Long oid, Integer catalog) {
    int result = 0;
    List<Filter> filters = new ArrayList<Filter>();
    filters.add(Filter.eq("oid", oid));
    filters.add(Filter.eq("catalog", catalog));
    List<Flow> tasks = findList(0, 1000, filters, null);
    if (tasks != null && tasks.size() > 0) {
      result = tasks.size();
      for (Flow task : tasks) {
        delete(task);
      }
    }
    return result;
  }
}